#include "user_io_i2c.h"

/*************************************************
  Function:       SCL_HIGH
  Description:    模拟I2C中的SCL置高动作
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SCL_HIGH(PERIPHERAL  Peripheral)
{
	GPIO_Set(&Peripheral.SCL,HIGH);
}

/*************************************************
  Function:       SCL_LOW
  Description:    模拟I2C中的SCL置低动作
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SCL_LOW(PERIPHERAL  Peripheral)
{
	GPIO_Set(&Peripheral.SCL,LOW);
}

/*************************************************
  Function:       SDA_HIGH
  Description:    模拟I2C中的SDA置高动作
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SDA_HIGH(PERIPHERAL  Peripheral)
{
	GPIO_Set(&Peripheral.SDA,HIGH);
}

/*************************************************
  Function:       SDA_LOW
  Description:    模拟I2C中的SDA置低动作
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SDA_LOW(PERIPHERAL  Peripheral)
{
	GPIO_Set(&Peripheral.SDA,LOW);
}

/*************************************************
  Function:       SDA_val
  Description:    模拟I2C中的读取SDA电平
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
uint32_t SDA_val(PERIPHERAL  Peripheral)
{
	return GPIO_Val_Read(Peripheral.SDA);
}

/*************************************************
  Function:       SDA_set_input
  Description:    将设备的SDA口设置为输入
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SDA_set_input(PERIPHERAL  Peripheral)
{
	FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.pin = Peripheral.SDA.PIN;              //pin引脚
	GPIO_InitStruct.mode = FL_GPIO_MODE_INPUT;  //输出模式：输入/输出/数字功能/模拟功能
	GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN; //输出模式：推挽输出/开漏输出
	GPIO_InitStruct.pull = FL_DISABLE;   //上拉使能
	FL_GPIO_Init(Peripheral.SDA.GROUP, &GPIO_InitStruct);
//	GPIO_Set_Mode(&Peripheral.SDA,GPIO_INPUT);
}

/*************************************************
  Function:       SDA_set_output
  Description:    将设备的SDA口设置为输出
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void SDA_set_output(PERIPHERAL  Peripheral)
{
	GPIO_Set_Mode(&Peripheral.SDA,GPIO_OUTPUT);
}

/*************************************************
  Function:       I2C_Peripheral_gpio_init
  Description:    对设备所使用的GPIO口初始化
  Input:          Peripheral：I2C设备
  Return:         无 
  other:
*************************************************/
void I2C_Peripheral_gpio_init(PERIPHERAL  Peripheral)
{
	SDA_HIGH(Peripheral);
	SCL_HIGH(Peripheral);
	Peripheral.SCL.mode = GPIO_OUTPUT;
	Peripheral.SCL.tpye = GPIO_PUSH;
	Peripheral.SCL.Remap = NULL;
	GPIO_Init(Peripheral.SCL);
	
	Peripheral.SDA.mode = GPIO_OUTPUT;
	Peripheral.SDA.tpye = GPIO_OPEN;
	Peripheral.SDA.Remap = NULL;
	GPIO_Init(Peripheral.SDA);
}


/*************************************************
  Function:       I2C_START
  Description:    模拟I2C中的启始协议
  Input:          要执行的设备
  Return:         无 
  other:
*************************************************/
void I2C_START(PERIPHERAL  Peripheral)
{
	SDA_set_output(Peripheral);
	SCL_HIGH(Peripheral);
	SDA_HIGH(Peripheral);
	__nop();
	SDA_LOW(Peripheral);
	__nop();
	SCL_LOW(Peripheral);
	__nop();
}

/*************************************************
  Function:       I2C_STOP
  Description:    模拟I2C中的停止协议
  Input:          要执行的设备
  Return:         无 
  other:
*************************************************/
void I2C_STOP(PERIPHERAL  Peripheral)
{
	SCL_LOW(Peripheral);
	SDA_set_output(Peripheral);
	SDA_LOW(Peripheral);
	__nop();
	SCL_HIGH(Peripheral);
	__nop();
	SDA_HIGH(Peripheral);
	__nop();
}

/*************************************************
  Function:       I2C_Send_ACK
  Description:    模拟I2C中的发送ACK动作
  Input:          要执行的设备
  Return:         无 
  other:
*************************************************/
void I2C_Send_ACK(PERIPHERAL  Peripheral)
{
	SCL_LOW(Peripheral);
	SDA_set_output(Peripheral);
	__nop();
	SDA_LOW(Peripheral);
	__nop();
	SCL_HIGH(Peripheral);
	__nop();
	SCL_LOW(Peripheral);
}

/*************************************************
  Function:       I2C_Send_NACK
  Description:    模拟I2C中的发送NACK动作
  Input:          要执行的设备
  Return:         无 
  other:
*************************************************/
void I2C_Send_NACK(PERIPHERAL  Peripheral)
{
	SCL_LOW(Peripheral);
	SDA_set_output(Peripheral);
	__nop();
	SDA_HIGH(Peripheral);
	__nop();
	SCL_HIGH(Peripheral);
	__nop();
	SCL_LOW(Peripheral);
}

/*************************************************
  Function:       I2C_Check_ACK
  Description:    模拟I2C中的检查ACK动作
  Input:          要执行的设备
  Return:         ACK应答结果，1：无应答。0：应答
  other:
*************************************************/
uint8_t I2C_Check_ACK(PERIPHERAL  Peripheral)
{
	uint16_t count = 0;
	SDA_HIGH(Peripheral);
	SDA_set_input(Peripheral);
	__nop();
	SCL_HIGH(Peripheral);
	__nop();
	while(SDA_val(Peripheral))
	{
		count++;
		if(count>200)
		{
			I2C_STOP(Peripheral);
			return 1;
		}
	}
	SCL_LOW(Peripheral);
	return 0;
}

/*************************************************
  Function:       I2C_Write_oneByte
  Description:    模拟I2C中的写1字节动作
  Input:          Peripheral:要执行的设备
                  data:发送的数据
  Return:         无 
  other:
*************************************************/
void I2C_Write_oneByte(PERIPHERAL  Peripheral,uint8_t data)
{
	uint8_t i;
	SDA_set_output(Peripheral);
	__nop();
	for(i=0;i<8;i++)
	{
		if(data & 0x80)
			SDA_HIGH(Peripheral);
		else
			SDA_LOW(Peripheral);
		data <<= 1;
		__nop();
		SCL_HIGH(Peripheral);
		__nop();
		SCL_LOW(Peripheral);
		if(data & 0x80)
		{
			SCL_LOW(Peripheral);
		}
		else
		{
			SCL_LOW(Peripheral);
			SDA_LOW(Peripheral);
		}
		__nop();
	}
}

/*************************************************
  Function:       I2C_Read_oneByte
  Description:    模拟I2C中的读1字节动作
  Input:          Peripheral:要执行的设备
  Return:         接收到的数据
  other:
*************************************************/
uint8_t I2C_Read_oneByte(PERIPHERAL  Peripheral)
{
	uint8_t data = 0;
	uint8_t i;
	SCL_LOW(Peripheral);
	SDA_set_input(Peripheral);
	__nop();
	for(i =0;i<8;i++)
	{
		SCL_LOW(Peripheral);
		__nop();
		SCL_HIGH(Peripheral);
		__nop();
		data <<= 1;
		if(SDA_val(Peripheral) == 1)
		{
			data |= 0x01;
		}
		else
		{
			data &= 0xFE;
		}
		SCL_LOW(Peripheral);
	}
	return data;
}
